// Javascript Viewer File
//
// Contains code for making pretty-looking presentations out of data .txt files.

// Create JS Useful Prototype
//		Useful functions from http://javascript.crockford.com/remedial.html 
//		AKA: Douglas Crockford

// Interpolate string.
//		Ex: "test{1}".supplant(["abc","def"]); ==> "testdef"
//		Ex: "test{bob}".supplant({"bob":"abc"}); ==> "testabc"
String.prototype.supplant = function (o) {
    return this.replace(/{([^{}]*)}/g,
        function (a, b) {
            var r = o[b];
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        }
    );
};
//	Turn html code into something that can be safely printed to html.
String.prototype.entityify = function () {
    return this.replace(/&/g, "&amp;").replace(/</g,
        "&lt;").replace(/>/g, "&gt;");
};
//	Return trimmed string.
String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, "");
}; 

/* Build a TOC from <h1>, <h2>, ... elements */
var buildToc = function(jq){

	/* Return s repeated i times. */
	var repeat = function( s, i ) {
			var a = new Array(i+1);
			return a.join(s);
		};
	var i = 0;
	var toc = "";

	// Add a unique ID value to each header element.
	jq.html(jq.html().replace( /<h([1-9])>(.+?)<\/h[1-9]>/g, 
			function(e){ 
				i++;
				toc = toc + repeat("&nbsp;", (parseInt(e.substring(2,3))-1)*4 ) + 
							"&#8226; <a href='#h_" + i + "'>" + e.substring(4, e.length-5) + "</a><br/>\n";
				return( e.substring(0,3) + " id='h_" + i + "' " + 
						e.substring(3, e.length-5).trim() + "</h" + e.substring(2,3) + ">");
			}));

	return toc;
}

// Apply dynamic formatting to page 
//	Assumes that incoming data will have unescaped code segments
//	Returns valid html markup.
var ConvertTags = function(s) {

	// Apply brushes as needed for code samples.
	//	REGEX notes:
	//		(.+?) applies to any thing but a newline (? means greedy)
	//		(\n) applies to newline
	// FUNCTION notes:
	//		add a div title for the type of code we're looking at.
	s = s.replace( /\[\[(html|js|cs)((.+?)|(\r\n?))*?\]\]/g, 
			function(e){ 
				// Remove [[ and ]]
				e = e.substring(2,e.length-2); 
				
				// replace tabs with 3 spaces
				// replace windows linebreaks with regular unix linebreaks
				//		Changing linebreaks helps us to not turn them into <br> chars later.
				e = e.replace( /\t/g, "    ");
				e = e.replace(/\r\n/g, "\n" ); 
				
				if( e.substring(0,4) == 'html' )
					return "<div class='codeTitle'>Html</div>" +
						"<pre class='brush: html'>" + e.substring(4).entityify() + "</pre>";
				else if ( e.substring(0,3) == 'css' )
					return "<div class='codeTitle'>CSS</div>" +
						"<pre class='brush: css'>" + e.substring(3).entityify() + "</pre>";
				else if ( e.substring(0,2) == 'js' )
					return "<div class='codeTitle'>Javascript</div>" +
						"<pre class='brush: js'>" + e.substring(2).entityify() + "</pre>";
				else
					return ('Unknown code ' + e);
					
			});
	

	// Find [[ ]] blocks.
	s = s.replace( /\[\[(h[0-9]|img|http)(.+?)\]\]/g, 
			function(s) {	
				// Strip [[ and ]] characters.
				s = s.substring(2,s.length-2);
				
				// Turn into formatted characters.
				//		Start with shortest matches & work up to longest.
				if( s.substring(0,2) == 'h1' || s.substring(0,2) == 'h2' || s.substring(0,2) == 'h3' ) {// (/h([0-9]) (.+?)/).test(s)
					// Create h1/h2/h3 titles from [[h1 Title!]]
					return "<h" + s.substring(1,2) + ">" + s.substring(3) + "</h" + s.substring(1,2) + ">";

				} else if( s.substring(0,4) == 'img ' ) {
					// Create image links from [[img sample.jpg]]
					return "<img src='" + s.substring(4) + "'/><br/>";
				
				} else if (s.substring(0,4) == "http") {
					// Create url links  from [[http://google.com]] or [[http://google.com Google]]

					// Space?
					if( s.indexOf(' ') == -1 ) {
						return "<a href='" + s + "'>" + s + "</a>";
					} else {
						// Split into parts
						var url = s.substring(0, s.indexOf(' ')).trim();
						var title = s.substring(url.length).trim();
						return "<a href='" + url + "'>" + title + "</a>";
					}
					
				} else {
					// Unknown pattern
					return s;
				}
			});
	
	
	// Create lists when we have lines tabbed over.
	//		Be sure to have after we've created code blocks.
	s = s.replace( /\t(.+?)\r\n/g, "<div class='list'>$1</div>" );
	
	
	
	// Replace \r\n with <br>
	//		Be sure to have after we've created the code blocks.
	s = s.replace( /\r\n/g,"<br>" );
	

	//alert(s);
	return s;
};

/* Replace the content of all notes with {{n}}, where n is the id
 	of location in the page */
var parseComments = function(jq) {
	
	var aComments = [];
	
	// Find {{ }} blocks and turn into comment divs.
	var s = jq.html().replace( /\{\{(.+?)\}\}/g, 
			function(s) {
				// Strip {{ and }} characters.
				s = s.substring(2,s.length-2);
				// Remove any html <?> line elements.
				s = s.replace(/<(.+?)>/g," ");
				// Add to object.
				return "---" + aComments.push(s) + "---";
			});
	
	jq.html(s);
	return aComments;
}
/* Add the comments back into the page */
var showComments = function(aNotes, jq){
	
	// Find {{ }} blocks and turn into comment divs.
	jq.html( jq.html().replace( /\-\-\-(.+?)\-\-\-/g, 
			function(s) {
				// Strip --- characters and turn " into ' to avoid breaking attr
				s = s.substring(3,s.length-3);
				s = ("" + aNotes[parseInt(s)]).trim().replace( /"/g, "'");
				// Add to image as an alt string.
				return '<img src="img/comment.png" width=12px height=12px '+
						'class="comment NavListItem" alt="' + s + '"/>';
			})
		);
	
}

var fixEasing = function() {
	//borrowed from jQuery easing plugin
	//http://gsgd.co.uk/sandbox/jquery.easing.php
	$.easing.elasout = function(x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	};
};


///////////////// Navigation

/* Build iteratable elements */
var buildNavList = function(jq) {

	// Select all items that will be navigated.
	$(":header,img,p,b,.codeTitle")
		.addClass('navListItem');
	
	/*
		.append("<img src='img/navListItem.png'/>")
		.click(function() {
			// Select item.
				$('.navListSelectedItem').removeClass('navListSelectedItem');		
				$(this).addClass('navListSelectedItem');

				// try to find it in the iterable list.
				// BROKEN
				selectNextIndex = -1;
				var jqList = $(".navListItem");
				var jqThis = $(this);
				while (	selectNextIndex <= jqList.length
						&& jqList.filter(":eq(" + selectNextIndex + ")").id != jqThis.id) {
					selectNextIndex++;
					alert( jqList.filter(":eq(" + selectNextIndex + ")"));
				}
			});
	*/
}


/* Create properties for selectNext to maintain
 * some global variables to maintain state between /next/ calls */
var selectNextIndex = -1;

/* Move to the next matching regex element */
var selectNext = function(option){
	
	// Increment counter 
	option ? selectNextIndex++ : selectNextIndex--;
	
	// Find nth header or image.
	var item = $(".navListItem").filter(":eq(" + selectNextIndex + ")");
	
	if( item.length > 0 ) {
		/* Apply formatting & scroll to selected item */
		$('.navListSelectedItem').removeClass('navListSelectedItem');		
		item.addClass('navListSelectedItem');
		
		// Look to see if the item has custom selection behavior
		if( item.hasClass('comment') ) {
			// Move the commentbox to this location & set content.
			$('#viewComment').show();
			
			$('#viewComment')
				.offset({top:item.offset().top-10,left:item.offset().left})
				.html(item.attr('alt'));
				
			$('#viewContent').animate({
					left: "20%",
					width: "80%"
				},300,function() {
					$.scrollTo(item.offset().top-20, 100, 200);
				});
		} else {
			// Hide commentbox & scroll.
			//	TODO: Only apply if we need the animation.
			$('#viewComment').hide();
			
			$('#viewContent').animate({
					left: "0%",
					width: "100%"
				},300,function() {
					$.scrollTo(item.offset().top-20, 300, 200);
				});
			
		}
	} else {
		// Stay on current index 
		option ? selectNextIndex-- : selectNextIndex++;
	}
}

/* Enable shortcut navigation keys */
var enableShortKeys = function() {
	
	
	$(document).shortkeys({
		' ':  function() {
			selectNext(true);
			},
		'right': function() {
			selectNext(true);
			},
		'left':  function() {
			selectNext(false);
			},
		'i': function() {
				$('i').toggle();
				$.scrollTo($('.navListSelectedItem'));
			},
	// Kill the up/down keys, as those disable the ability to capture left/right.
		'up':  function() {},
		'down': function() {},
//		'backspace': function() {
//			Select(FindNext("backspace"));
//			},
		}
	);

};

/* Setup handlers to increase or decrease font size for the document. */
var enableViewControls = function() {
	var b = $('body')
	$('#viewControl_Plus').click( function() {
		b.css('font-size', parseInt(b.css('font-size')) + 2 + "px");
	});
	$('#viewControl_Minus').click( function() {
		b.css('font-size', parseInt(b.css('font-size')) - 2 + "px");
	});
}

